#ifndef _CONSOLE_H
#define _CONSOLE_H


#include "video.h"
#include "keyboard.h"


#define BUFFER_LENGTH 60
#define CONSOLES_COUNT 4

/*
 * Tipo de datos: bufferT
 * ----------------------
 * Estructura para administrar el buffer del teclado. Primero, se coloca cada
 * scancode que se recibe por la interrupcion en una cola circular.  Luego se
 * colocan las teclas en este buffer. Cuando se solicita un caracter, si no hay
 * en el buffer, se lo llena (utilizando el buffer de scancodes) hasta recibir
 * un enter.
 * El campo vec es un puntero a char donde se almacenan los ASCIIs recibidos.
 * El entero pos indica la posicion actual dentro del buffer. Dicha posicion
 * puede cambiar debido al uso de las flechas o las teclas inicio y fin.
 * El entero dim indica la dimension real del vector ya que puede no estar
 * completo. Por ultimo el entero begin indica a partir de que caracter hay
 * que devolver.
 */
typedef struct {
	int vec[BUFFER_LENGTH];
	unsigned int begin, pos, dim;
} bufferT;

/*
 * Tipo de datos: consoleT
 * -----------------------
 * Estructura para administrar una consola. El primer campo es el videoT que se
 * utiliza para manejar el display. El segundo es una cola de scancodes. En la
 * misma se almacenan los scancodes que van arribando para algun proceso de
 * esta consola. El tercero es un bufferT como el explicado arriba. El ultimo
 * es una bandera que en caso de ser 0 indica que hay basura en la estructura y
 * en cualquier otro caso no.
 */
typedef struct{
	videoT v;
	keyboardT k;
	bufferT b;
	int exists;
} consoleT;


/*
 * Funcion: init_tty
 * -----------------
 * Se encarga de inicializar el vector de consolas sin crear ninguna de ellas.
 * Debe ser invocada previo al uso de cualquiera de las otras funciones.
 */
void init_tty(void);

/*
 * Funcion: new_console
 * --------------------
 * Se encarga de crear una nueva consola y registrarla en el vector de consolas
 * recibido como primer parametro el numero de consola. Tambien la resgistra
 * como la consola activa y lanza un task shell. En caso de que el
 * indice sea invalido o la terminal solicitada ya exista retorna 0 de lo
 * contrario regresa 1. Los ultimos 2 parametros son utilizados para
 * inicializar el video.
 */
int new_console(unsigned int index, unsigned int cursor, int active);

/*
 * Funcion: switch_console
 * -----------------------
 * Es utilizada cuando se requiere cambiar de consola activa. El parametro es el
 * numero de consola a la cual se desea cambiar. En caso de que la
 * consola no exista o el indice sea invalido retorna 0 y de lo contrario 1.
 */
int switch_console(int index);

/*
 * Funcion: get_console_video
 * --------------------------
 * Devuelve un puntero al videoT asociado a una consola.
 */
videoT *get_console_video(unsigned int index);

/*
 * Funcion: get_console_by_index
 * -----------------------------
 * Devuelve una consola del vector de consolas por su indice.
 */
consoleT *get_console_by_index(unsigned int index);

/*
 * Funcion: console_exists
 * -----------------------
 * Esta funcion es utilizada cuando es necesario determinar si una de las
 * consolas del vector de consolas existe o no. En caso afirmativo retorna 1 y
 * de lo contrario 0.
 */
int console_exists(unsigned int index);

/*
 * Funciones: sc_enqueue, sc_dequeue, sc_queue_is_empty, sc_queue_is_full
 * ----------------------------------------------------------------------
 * Estas funciones son wrappers para acceder encolar, desencolar y consultar
 * si la cola del teclado esta vacia o llen.
 */
int sc_enqueue(unsigned char key);
int sc_dequeue(unsigned char *key);
int sc_queue_is_empty(void);
int sc_queue_is_full(void);

/*
 * Funciones: get_keyboard_modifiers, set_keyboard_modifiers
 * ---------------------------------------------------------
 * Sirven para lectura y escritura del estado las teclas modificadoras,
 * respectivamente.
 */
int get_keyboard_modifiers(void);
void set_keyboard_modifiers(int modifiers);


/*
 * Funcion: get_active_tty_num
 * ---------------------------
 * Devuelve el numero de la consola activa.
 */
unsigned int get_active_tty_num(void);

/*
 * Funcion: free_console
 * ---------------------
 * Se encarga de registrar en el vector de consolas recibido como primer
 * parametro que la consola indicada ya no existe. En caso de que el indice
 * solicitado no exista retorna 0 y de lo contrario 1.
 */
int free_console(unsigned int index);

/*
 * Funcion: init_buffer
 * --------------------
 * Inicializa un bufferT.
 */
void init_buffer(bufferT *b);

/*
 * Funcion: buffer_insert
 * ----------------------
 * Se encarga de insertar un caracter en el buffer de la consola.
 * En caso de que no haya lugar o se produzca cualquier otro error retorna 0
 * y de lo contrario 1.
 */
int buffer_insert(consoleT *c, int key);

/*
 * Funcion: buffer_delete
 * ----------------------
 * Se encarga de eliminar el caracter que se encuentra en la posicion anterior
 * del buffer de la consola. En caso de producirse algun error, retorna 0 y de
 * lo contrario 1.
 */
void buffer_delete(consoleT *c);


#endif /* _CONSOLE_H */

